{%- if let Some(docstring) = docstring %}
{{ crate::utils::prefix_lines(docstring, "// ") }}
{%- endif %}
type {{ name }} string

const (
    {% if values.is_empty() %}
    // no values defined for {{ name }}
    {%- else %}
    {%- for (value, m_docstring) in values %}
    {%- if let Some(docstring) = m_docstring %}
    {{ crate::utils::prefix_lines(docstring, "// ") }}
    {%- endif %}
    {{ name }}{{ value }} {{ name }} = "{{ value }}"
    {%- endfor %}
    {%- endif %}
)

// Values returns all allowed values for the {{ name }} type.
func ({{ name }}) Values() []{{ name }} {
    return []{{ name }}{
        {%- for (value, _) in values %}
        {{ name }}{{ value }},
        {%- endfor %}
    }
}

// IsValid checks whether the given {{ name }} value is valid.
func (e {{ name }}) IsValid() bool {
  {% if dynamic %}
  // dynamic enums are always valid
  return true
  {% else %}
  for _, v := range e.Values() {
      if e == v {
          return true
      }
  }
  return false
  {% endif %}
}

// MarshalJSON customizes JSON marshaling for {{ name }}.
func (e {{ name }}) MarshalJSON() ([]byte, error) {
    if !e.IsValid() {
        return nil, fmt.Errorf("invalid {{ name }}: %q", e)
    }
    return json.Marshal(string(e))
}

// UnmarshalJSON customizes JSON unmarshaling for {{ name }}.
func (e *{{ name }}) UnmarshalJSON(data []byte) error {
    var s string
    if err := json.Unmarshal(data, &s); err != nil {
        return err
    }
    *e = {{ name }}(s)
    if !e.IsValid() {
        return fmt.Errorf("invalid {{ name }}: %q", s)
    }
    return nil
}

func (e *{{ name }}) Decode(holder *cffi.CFFIValueEnum, typeMap baml.TypeMap) {
    name := holder.Name
    if name.Name != "{{ name }}" && name.Namespace != {{ pkg.namespace() }} {
        panic(fmt.Sprintf("expected {{ pkg.name() }}.{{ name }}, got %s.%s", string(name.Namespace.String()), string(name.Name)))
    }
    value := holder.Value
    *e = {{ name }}(value)
}

func (e {{ name }}) Encode() (*cffi.CFFIValueHolder, error) {
    return baml.EncodeEnum(e.BamlEncodeName, string(e), false)
}

func (e {{ name }}) BamlTypeName() string {
    return "{{ name }}"
}

func (u {{ name }}) BamlEncodeName() *cffi.CFFITypeName {
    return &cffi.CFFITypeName{
        Name:      "{{ name }}",
        Namespace: {{ pkg.namespace() }},
    }
}
